package com.v95.benchmark.whetstone;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Button;

public class Whetstone extends Activity {
	/** Called when the activity is first created. */

	private static long secs_inicial;
	private static EditText et;
	private static Button bt1;
	private static Button bt2;

	private static float loop_time[];
	private static float loop_mops[];
	private static float loop_mflops[];
	private static float TimeUsed;
	private static float mwips;
	private static String headings[];
	private static float Check;
	private static float results[];
	private static float x, y, z;

	private void imprimir(String texto) {
		et.append(texto);
	}

	private float what_time() {
		return ((float)(System.currentTimeMillis() - secs_inicial))*0.001f;
	}

	private void pa(float e[], float t, float t2) {
		for (long j = 0; j < 6; j++) {
			e[0] = (e[0] + e[1] + e[2] - e[3]) * t;
			e[1] = (e[0] + e[1] - e[2] + e[3]) * t;
			e[2] = (e[0] - e[1] + e[2] + e[3]) * t;
			e[3] = (-e[0] + e[1] + e[2] + e[3]) / t2;
		}

		return;
	}

	private void po(float e1[], long j, long k, long l) {
		e1[(int) j] = e1[(int) k];
		e1[(int) k] = e1[(int) l];
		e1[(int) l] = e1[(int) j];
		return;
	}

	private void p3(float t, float t1, float t2) {
		x = y;
		y = z;
		x = t * (x + y);
		y = t1 * (x + y);
		z = (x + y) / t2;
		return;
	}

	private void pout(String title, float ops, int type, float checknum,
			float time, int calibrate, int section) {
		float mops, mflops;

		Check = Check + checknum;
		loop_time[section] = time;
		headings[section] = title;
		TimeUsed = TimeUsed + time;
		if (calibrate == 1)

		{
			results[section] = checknum;
		}
		if (calibrate == 0) {
			imprimir(headings[section]);

			if (type == 1) {
				if (time > 0) {
					mflops = ops / (1000000L * time);
				} else {
					mflops = 0;
				}
				loop_mops[section] = 99999;
				loop_mflops[section] = mflops;
				imprimir("\t\t" + loop_mflops[section] + "\n");
			} else {
				if (time > 0) {
					mops = ops / (1000000L * time);
				} else {
					mops = 0;
				}
				loop_mops[section] = mops;
				loop_mflops[section] = 0;
				imprimir("\t\t" + loop_mops[section] + "\n");
			}
		}

		return;
	}

	void whetstones(long xtra, long x100, int calibrate) {

		long n1, n2, n3, n4, n5, n6, n7, n8, i, ix, n1mult;
		float x, y, z;
		long j, k, l;
		float e1[] = new float[4];
		float timea;
		float timeb;

		float t = 0.49999975f;
		float t0 = t;
		float t1 = 0.50000025f;
		float t2 = 2.0f;

		Check = 0.0f;

		n1 = 12 * x100;
		n2 = 14 * x100;
		n3 = 345 * x100;
		n4 = 210 * x100;
		n5 = 32 * x100;
		n6 = 899 * x100;
		n7 = 616 * x100;
		n8 = 93 * x100;
		n1mult = 10;

		/* Section 1, Array elements */

		e1[0] = 1.0f;
		e1[1] = -1.0f;
		e1[2] = -1.0f;
		e1[3] = -1.0f;
		timea = what_time();
		{
			for (ix = 0; ix < xtra; ix++) {
				for (i = 0; i < n1 * n1mult; i++) {
					e1[0] = (e1[0] + e1[1] + e1[2] - e1[3]) * t;
					e1[1] = (e1[0] + e1[1] - e1[2] + e1[3]) * t;
					e1[2] = (e1[0] - e1[1] + e1[2] + e1[3]) * t;
					e1[3] = (-e1[0] + e1[1] + e1[2] + e1[3]) * t;
				}
				t = 1.0f - t;
			}
			t = t0;
		}
		timeb = (what_time() - timea) / (float) (n1mult);
		pout("N1 floating point\0", (float) (n1 * 16) * (float) (xtra), 1,
				e1[3], timeb, calibrate, 1);

		/* Section 2, Array as parameter */

		timea = what_time();
		{
			for (ix = 0; ix < xtra; ix++) {
				for (i = 0; i < n2; i++) {
					pa(e1, t, t2);
				}
				t = 1.0f - t;
			}
			t = t0;
		}
		timeb = what_time() - timea;
		pout("N2 floating point\0", (float) (n2 * 96) * (float) (xtra), 1,
				e1[3], timeb, calibrate, 2);

		/* Section 3, Conditional jumps */
		j = 1;
		timea = what_time();
		{
			for (ix = 0; ix < xtra; ix++) {
				for (i = 0; i < n3; i++) {
					if (j == 1)
						j = 2;
					else
						j = 3;
					if (j > 2)
						j = 0;
					else
						j = 1;
					if (j < 1)
						j = 1;
					else
						j = 0;
				}
			}
		}
		timeb = what_time() - timea;
		pout("N3 if then else  \0", (float) (n3 * 3) * (float) (xtra), 2,
				(float) (j), timeb, calibrate, 3);

		/* Section 4, Integer arithmetic */
		j = 1;
		k = 2;
		l = 3;
		timea = what_time();
		{
			for (ix = 0; ix < xtra; ix++) {
				for (i = 0; i < n4; i++) {
					j = j * (k - j) * (l - k);
					k = l * k - (l - j) * k;
					l = (l - k) * (k + j);
					e1[(int) (l - 2)] = j + k + l;
					e1[(int) (k - 2)] = j * k * l;
				}
			}
		}
		timeb = what_time() - timea;
		x = e1[0] + e1[1];
		pout("N4 fixed point   \0", (float) (n4 * 15) * (float) (xtra), 2, x,
				timeb, calibrate, 4);

		/* Section 5, Trig functions */
		x = 0.5f;
		y = 0.5f;
		timea = what_time();
		{
			for (ix = 0; ix < xtra; ix++) {
				for (i = 1; i < n5; i++) {
					x = t
							* (float) java.lang.Math.atan(t2
									* java.lang.Math.sin(x)
									* java.lang.Math.cos(x)
									/ (java.lang.Math.cos(x + y)
											+ java.lang.Math.cos(x - y) - 1.0));
					y = t
							* (float) java.lang.Math.atan(t2
									* java.lang.Math.sin(y)
									* java.lang.Math.cos(y)
									/ (java.lang.Math.cos(x + y)
											+ java.lang.Math.cos(x - y) - 1.0));
				}
				t = 1.0f - t;
			}
			t = t0;
		}
		timeb = what_time() - timea;
		pout("N5 sin,cos,etc.  \0", (float) (n5 * 26) * (float) (xtra), 2, y,
				timeb, calibrate, 5);

		/* Section 6, Procedure calls */
		x = 1.0f;
		y = 1.0f;
		z = 1.0f;
		timea = what_time();
		{
			for (ix = 0; ix < xtra; ix++) {
				for (i = 0; i < n6; i++) {
					p3(t, t1, t2);
				}
			}
		}
		timeb = what_time() - timea;
		pout("N6 floating point\0", (float) (n6 * 6) * (float) (xtra), 1, z,
				timeb, calibrate, 6);

		/* Section 7, Array refrences */
		j = 0;
		k = 1;
		l = 2;
		e1[0] = 1.0f;
		e1[1] = 2.0f;
		e1[2] = 3.0f;
		timea = what_time();
		{
			for (ix = 0; ix < xtra; ix++) {
				for (i = 0; i < n7; i++) {
					po(e1, j, k, l);
				}
			}
		}
		timeb = what_time() - timea;
		pout("N7 assignments   \0", (float) (n7 * 3) * (float) (xtra), 2,
				e1[2], timeb, calibrate, 7);

		/* Section 8, Standard functions */
		x = 0.75f;
		timea = what_time();
		{
			for (ix = 0; ix < xtra; ix++) {
				for (i = 0; i < n8; i++) {
					x = (float) java.lang.Math.sqrt(java.lang.Math
							.exp(java.lang.Math.log(x) / t1));
				}
			}
		}
		timeb = what_time() - timea;
		pout("N8 exp,sqrt etc. \0", (float) (n8 * 4) * (float) (xtra), 2, x,
				timeb, calibrate, 8);

		return;
	}

	private void calcular_whetstone() {
		int count = 10, calibrate = 1;
		long xtra = 1;
		long x100 = 100;
		int duration = 100;

		secs_inicial = System.currentTimeMillis();

		imprimir("Calibrate\n");

		do {
			TimeUsed = 0;

			whetstones(xtra, x100, calibrate);

			imprimir(TimeUsed + " Seconds " + xtra + " Passes (x 100)\n");
			calibrate = calibrate + 1;
			count = count - 1;
			if (TimeUsed > 2.0)
				count = 0;
			else
				xtra = xtra * 5;
		} while (count > 0);

		if (TimeUsed > 0)
			xtra = (long) ((float) (duration * xtra) / TimeUsed);
		if (xtra < 1)
			xtra = 1;

		calibrate = 0;

		imprimir("\nUse " + xtra + " passes (x 100)\n");

		imprimir("\nLoop content\t\t\tMFLOPS/MOPS\n\n");

		TimeUsed = 0;
		whetstones(xtra, x100, calibrate);

		imprimir("\nMWIPS: ");
		if (TimeUsed > 0)
			mwips = (float) (xtra) * (float) (x100) / (10 * TimeUsed);
		else
			mwips = 0;

		imprimir(mwips + "\n\n");

		if (Check == 0)
			imprimir("Wrong answer");
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		et = (EditText) findViewById(R.id.consola);
		bt1 = (Button) findViewById(R.id.boton_salir);
		bt2 = (Button) findViewById(R.id.boton_comenzar);

		loop_time = new float[9];
		loop_mops = new float[9];
		loop_mflops = new float[9];
		headings = new String[9];
		results = new float[9];

		bt1.setOnClickListener(new View.OnClickListener() {
			public void onClick(View view) {
				finish();
			}
		});

		bt2.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				calcular_whetstone();
			}
		});

		imprimir("Simple Precision C/C++ Whetstone Benchmark\n\n");
	}
}